package org.brakepedal.server.support.controller.exceptionHandler;

import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.brakepedal.server.support.exception.BusinessException;
import org.brakepedal.server.support.http.*;
import org.brakepedal.server.support.interceptor.Handle404Interceptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.io.OutputStream;

/**
 * Date: 2023/2/11 14:12
 *
 */
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class BusinessExceptionHandleAdvice {

    @Nullable
    private Handle404Interceptor handle404Interceptor;

    @Autowired(required = false)
    public void setHandle404Interceptor(@Nullable Handle404Interceptor handle404Interceptor) {
        this.handle404Interceptor = handle404Interceptor;
    }

    // 处理缺失请求参数的异常
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ComResponseBody handleMissingRequestParamException(@NotNull MissingServletRequestParameterException e) {
        return (ComResponseBody) ComResponseBody.errorMsg(ResponseBodyMsg.error("require a '" + e.getParameterType() + "' type param '" + e.getParameterName() + "'"));
    }

    @ExceptionHandler(BusinessException.class)
    public AbsResponseBody handleBusinessException(@NotNull BusinessException e) {
        return ComResponseBody.builder()
                .code(ResponseBodyCode.BAD_REQUEST)
                .status(ResponseBodyStatus.ERROR)
                .msg(ResponseBodyMsg.custom(e.getMessage()))
                .errorType(e.getClass().getSimpleName())
                .build();
    }

    // 捕获其他未处理的异常，并返回错误信息
    @ExceptionHandler(HttpClientErrorException.NotFound.class)
    public void handleUncaughtException(@NotNull Exception e, @NotNull HttpServletResponse response) throws Exception {
        log.info("catch exception '{}', response code: {}", e, response.getStatus());
        if (handle404Interceptor == null || handle404Interceptor.getNotFoundPageFileBytes().length == 0) {
            throw e;
        }
        response.setStatus(HttpStatus.OK.value());
        OutputStream ops = response.getOutputStream();
        response.setContentType("text/html");
        ops.write(handle404Interceptor.getNotFoundPageFileBytes());
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public AbsResponseBody handleMethodArgumentTypeMismatchException(@NotNull MethodArgumentTypeMismatchException e) {
        return ComResponseBody.builder()
                .code(ResponseBodyCode.BAD_REQUEST)
                .status(ResponseBodyStatus.ERROR)
                .msg(ResponseBodyMsg.custom(
                        String.format("unsupported algorithm '%s' in path variable '%s'", e.getValue(),e.getName())
                ))
                .errorType(e.getClass().getSimpleName())
                .build();
    }


    @ExceptionHandler(HttpMessageNotReadableException.class)
    public AbsResponseBody handleHttpMessageNotReadableException(@NotNull HttpMessageNotReadableException e) {
        return ComResponseBody.builder()
                .code(ResponseBodyCode.BAD_REQUEST)
                .status(ResponseBodyStatus.ERROR)
                .msg(ResponseBodyMsg.custom(
                        String.format(e.getMessage())
                ))
                .errorType("HttpMessageNotReadableException")
                .build();
    }
}
